package com.xtaller.sdboot.controller;

import com.alibaba.fastjson.JSONObject;
import com.xtaller.sdboot.entity.*;
import com.xtaller.sdboot.service.*;
import com.xtaller.sdboot.util.PermissionUtil;
import com.xtaller.sdboot.utils.helper.ValidatorHelper;
import com.xtaller.sdboot.vo.IdsVO;
import com.xtaller.sdboot.vo.TreeVO;
import com.xtaller.sdboot.core.R;
import com.xtaller.sdboot.core.Status;
import com.xtaller.sdboot.utils.annotation.Log;
import com.xtaller.sdboot.utils.annotation.Permission;
import com.xtaller.sdboot.core.base.BaseController;
import com.xtaller.sdboot.core.base.BaseEntity;
import com.xtaller.sdboot.utils.helper.JsonHelper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/** 
* 代码生成 
* @author: Taller  
* @date: 2020-02-07 15:56:30
* @Description: 用户角色控制器 
*/
@Slf4j
@RestController 
@RequestMapping("/v1/iam/role") 
public class IamRoleController extends BaseController<IamRole> {
    @Autowired private IamRoleService roleService;
    @Autowired private IamUserRoleService userRoleService;
    @Autowired private IamApplicationPermissionService applicationPermissionService;
    @Autowired private IamPermissionService permissionService;
    @Autowired private IamModuleService moduleService;
    @Autowired private IamRolePermissionService rolePermissionService;

    @ApiOperation("表格")
    @Permission(authorities = "iam:role:platform:data:list")
    @GetMapping("/platform/list")
    public Object platformGetByPage(HttpServletRequest request) throws Exception {
        return super.getByPage(request);
    }

    @ApiOperation("创建")
    @Permission(authorities = "iam:role:platform:opt:create")
    @PostMapping("/platform")
    public Object platformCreateEntity(@Valid @RequestBody IamRole entity, HttpServletRequest request) throws Exception {
        return super.createEntity(entity, request);
    }

    @ApiOperation("编辑")
    @Permission(authorities = "iam:role:platform:opt:update")
    @PutMapping("/platform/{id}")
    public Object platformUpdateEntity(@PathVariable("id") Serializable id, @Valid @RequestBody IamRole entity, HttpServletRequest request) throws Exception {
        return super.updateEntity(id, entity, request);
    }

    @ApiOperation("删除")
    @Permission(authorities = "iam:role:platform:opt:delete")
    @DeleteMapping("/platform/{id}")
    public Object platformDeleteEntity(@PathVariable("id") Serializable id, HttpServletRequest request) throws Exception {
        return super.deleteEntity(id, request);
    }

    @GetMapping("/application")
    @ApiOperation("应用角色")
    @Permission(authorities = "iam:app:role:data:list")
    public Object getRoleByApplicationId() {
        var qw = new QueryWrapper<IamRole>();
        qw.lambda().select(BaseEntity::getId, IamRole::getName, IamRole::getAppId)
                .eq(IamRole::getAppId, applicationId.get())
                .eq(IamRole::getState, 1)
                .orderByDesc(IamRole::getGrade);
        var data = roleService.getList(qw);
        return R.ok(data);
    }

    @PutMapping("/application/{uid}")
    @ApiOperation("设置应用角色")
    @Permission(authorities = "iam:app:role:opt:set")
    public Object setRole(@PathVariable String uid,
                          @RequestBody @Valid List<IdsVO> ids) {
        var urs = new ArrayList<IamUserRole>();
        if(ids.size() == 0){
            userRoleService.initRole(uid, applicationId.get());
            permissionUtil.updateAppCache(uid, -1, Arrays.asList(""));
            return R.ok("设置成功");
        }
        ids.stream().forEach(x -> {
            var ur = new IamUserRole();
            ur.setAppId(applicationId.get());
            ur.setUserId(uid);
            ur.setRoleId(x.getValue());
            urs.add(ur);
        });
        if(userRoleService.setRole(urs)){
            var roleIds = urs.stream().map(x -> x.getRoleId()).collect(Collectors.toList());
            permissionUtil.updateAppCache(uid, -1, roleIds);
            return R.ok("设置成功");
        }
        return R.error(Status.FAIL_EXCEPTION);
    }

    @GetMapping("/permission/{id}")
    @ApiOperation("应用权限")
    @Permission(authorities = "iam:role:permission:data:list")
    public Object getPermissionByRole(@PathVariable("id") Serializable id) throws Exception {
        // 读取应用下所有的权限信息
        var apQw = new QueryWrapper<IamApplicationPermission>();
        apQw.lambda().
                eq(IamApplicationPermission::getAppId, applicationId.get());
        var aps = applicationPermissionService.getList(apQw);
        var permissionIds = aps.stream().map(x -> x.getPermissionId()).collect(Collectors.toList());
        // 读取权限
        var pQw = new QueryWrapper<IamPermission>();
        pQw.lambda()
                .eq(IamPermission::getState, 1)
                .in(IamPermission::getId, permissionIds)
                .orderByDesc(IamPermission::getSortId)
                .orderByDesc(IamPermission::getGroups)
                .orderByDesc(IamPermission::getPosition);
        var permissions = permissionService.getList(pQw);

        // 读取所属模块
        var moduleIds = permissions
                            .stream().map(x -> x.getModuleId()).collect(Collectors.toList())
                            .stream().distinct().collect(Collectors.toList());
        var mQw = new QueryWrapper<IamModule>();
        mQw.lambda()
                .in(IamModule::getId, moduleIds)
                .eq(IamModule::getState, 1)
                .orderByDesc(IamModule::getSortId);
        var modules = moduleService.getList(mQw);

        // 读取当前已选择权限
        var roleQw = new QueryWrapper<IamRolePermission>();
        roleQw.lambda()
                .eq(IamRolePermission::getRoleId, id);
        var rps = rolePermissionService.getList(roleQw);

        return R.ok(formatterAppPermission(rps, modules, permissions));
    }

    @Autowired private PermissionUtil permissionUtil;

    @PutMapping("/permission/{id}")
    @ApiOperation("设置权限")
    @Permission(authorities = "iam:role:permission:opt:permission")
    public Object setPermissionByAppId(@PathVariable("id") String id, @RequestBody @Valid List<TreeVO> trees){
        var rps = new ArrayList<IamRolePermission>();
        trees.stream().forEach(x -> {
            var rp = new IamRolePermission();
            rp.setRoleId(id);
            rp.setPermissionId(x.getNodeId());
            rps.add(rp);
        });

        if(rolePermissionService.setPermissions(id, rps)) {
            // Todo 调整角色权限
            permissionUtil.updateRolePermission(id);
            return R.ok("数据调整成功", JsonHelper.create("id", id));
        }else {
            return R.error(Status.FAIL_OPERATION);
        }
    }

    @ApiOperation("表格")
    @Permission(authorities = "iam:role:data:list")
    @Override
    public Object getByPage(HttpServletRequest request) throws Exception {
        return super.getByPage(setAppId(request));
    }

    @Log(value = "create")
    @ApiOperation("创建")
    @Permission(authorities = "iam:role:opt:create")
    @Override
    public Object createEntity(@Valid @RequestBody IamRole entity, HttpServletRequest request) throws Exception {
        request = setAppId(request);
        return super.createEntity(entity, request);
    }

    @Log(value = "update")
    @ApiOperation("编辑")
    @Permission(authorities = "iam:role:opt:update")
    @Override
    public Object updateEntity(@PathVariable("id") Serializable id, @Valid @RequestBody IamRole entity, HttpServletRequest request) throws Exception {
        return super.updateEntity(id, entity, request);
    }

    @Log(value = "delete")
    @ApiOperation("删除")
    @Permission(authorities = "iam:role:opt:delete")
    @Override
    public Object deleteEntity(@PathVariable("id") Serializable id, HttpServletRequest request) throws Exception {
        return super.deleteEntity(id, request);
    }

    @Override
    protected String beforeCreate(BaseEntity entity) throws Exception {
        var model = (IamRole) entity;
        var appId = model.getAppId() == null ? applicationId.get() : model.getAppId();
        var qw = new QueryWrapper<IamRole>();
        qw.lambda()
                .eq(IamRole::getName, model.getName())
                .eq(IamRole::getAppId, appId);
        if(roleService.getList(qw).size() > 0){
            return "角色名称已经存在";
        }
        model.setAppId(appId);
        return super.beforeCreate(model);
    }

    @Override
    protected String beforeUpdate(BaseEntity entity) throws Exception {
        var model = (IamRole) entity;
        var appId = model.getAppId() == null ? applicationId.get() : model.getAppId();
        var qw = new QueryWrapper<IamRole>();
        qw.lambda()
                .ne(BaseEntity::getId, model.getId())
                .eq(IamRole::getName, model.getName())
                .eq(IamRole::getAppId, appId);
        if(roleService.getList(qw).size() > 0){
            return "角色名称已经存在";
        }
        return super.beforeUpdate(entity);
    }

    @Override
    protected String beforeDelete(BaseEntity entity) throws Exception {
        var qw = new QueryWrapper<IamUserRole>();
        qw.lambda()
                .eq(IamUserRole::getRoleId, entity.getId())
                .eq(IamUserRole::getAppId, applicationId.get());
        if(userRoleService.getList(qw).size() > 0){
            return "当前角色正在使用,禁止删除";
        }
        return super.beforeDelete(entity);
    }

    @Override
    protected String afterCreated(BaseEntity entity) throws Exception {
        roleService.initDefault((IamRole) entity);
        return super.afterCreated(entity);
    }

    @Override
    protected String afterUpdated(BaseEntity oldEntity, BaseEntity newEntity) throws Exception {
        roleService.initDefault((IamRole) newEntity);
        return super.afterUpdated(oldEntity, newEntity);
    }

    /**
     * 应用权限数据整合
     * */
    private List<JSONObject> formatterAppPermission(List<IamRolePermission> aps,
                                                    List<IamModule> modules,
                                                    List<IamPermission> permissions){
        var data = JsonHelper.list();
        if(modules.size() > 0){
            modules.stream().forEach(module -> {
                var top = JsonHelper.create("id", module.getId())
                        .put("title", module.getName())
                        .put("parentId", 0)
                        .put("checkArr", checkArr(aps, module.getId()))
                        .put("children", JsonHelper.list());
                if(permissions.size() > 0){
                    // 取出模块下数据
                    var modulePermissions = getPermissionByModuleId(permissions, module.getId());
                    // 取出模块下的功能菜单
                    var parents = getPermissionByParentId(modulePermissions, module.getId(), "menu", true);
                    var parentsJson = JsonHelper.o2l(parents);

                    parentsJson.stream().forEach(o -> {
                        var sub = getPermissionByParentId(modulePermissions, o.getString("id"), "menu", false);
                        var subs = JsonHelper.o2l(sub);
                        if(sub.size() > 0){
                            subs.stream().forEach(s -> {
                                var ps = getPermissionByParentId(modulePermissions, s.getString("id"), "auth", false);
                                s.put("id", s.getString("id"));
                                s.put("parentId", s.getString("parentId"));
                                s.put("title", s.getString("name"));
                                s.put("checkArr", checkArr(aps, s.getString("id")));
                                s.put("children", format2Tree(aps, ps));
                            });
                        }
                        o.put("id", o.getString("id"));
                        o.put("parentId", o.getString("moduleId"));
                        o.put("title", o.getString("name"));
                        o.put("checkArr", checkArr(aps, o.getString("id")));
                        o.put("children", subs);
                    });
                    top.put("children", parentsJson);
                    data.add(top);
                }
            });
        }
        return data;
    }

    /**
     * 获取权限父级数据
     * */
    public List<IamPermission> getPermissionByParentId(List<IamPermission> permissions, String id, String isMenu, boolean isFun){
        if("menu".equals(isMenu)){
            if(isFun){
                var list = permissions.stream()
                        .filter(x -> x.getModuleId().equals(id))
                        .filter(x -> x.getGroups().equals(isMenu))
                        .collect(Collectors.toList());
                return list.stream().filter(x -> x.getUri().length() == 0).collect(Collectors.toList());
            }
            var list = permissions.stream()
                    .filter(x -> x.getParentId().equals(id))
                    .filter(x -> x.getGroups().equals(isMenu))
                    .collect(Collectors.toList());
            return list.stream().filter(x -> !x.getParentId().equals(x.getModuleId())).collect(Collectors.toList());
        }
        return permissions.stream()
                .filter(x -> x.getParentId().equals(id))
                .filter(x -> x.getGroups().equals(isMenu))
                .collect(Collectors.toList());
    }

    /**
     * 读取模块菜单
     * */
    private List<IamPermission> getPermissionByModuleId(List<IamPermission> permissions, String moduleId){
        var list = new ArrayList<IamPermission>();
        if(permissions.size() > 0) {
            permissions.stream()
                    .filter(permission -> permission.getModuleId().equals(moduleId))
                    .forEach(permission -> {
                        list.add(permission);
                    });
        }
        return list;
    }

    /**
     * 树形选中
     * */
    private List<JSONObject> checkArr(List<IamRolePermission> aps, String permissionId){
        var list = JsonHelper.list();
        var tem = JsonHelper.create("type", 0).put("isChecked", 0);
        if(aps.size() > 0){
            var opt = aps.stream().filter(ra -> ra.getPermissionId().equals(permissionId)).findFirst();
            if(opt.isPresent()){
                tem.put("isChecked", 1);
            }
        }
        list.add(tem);
        return list;
    }

    /**
     * 格式化为树格式
     * */
    private List<JSONObject> format2Tree(List<IamRolePermission> aps, List<IamPermission> permissions){
        var list = JsonHelper.list();
        Collections.sort(permissions, new IamPermissionPositionComparetor());
        if(permissions.size() > 0){
            permissions.stream().forEach(permission -> {
                var m = JsonHelper.create("id", permission.getId())
                        .put("title", formatterPosition(permission.getPosition()) + permission.getName())
                        .put("parentId", permission.getParentId())
                        .put("checkArr", checkArr(aps, permission.getId()));
                list.add(m);
            });
        }
        return list;
    }
    /**
     * 给权限排序
     * */
    public class IamPermissionPositionComparetor implements Comparator<IamPermission> {
        @Override
        public int compare(IamPermission h1, IamPermission h2) {
            if (h1.getPosition() < h2.getPosition()) {
                return 1;
            } else if (h1.getPosition().equals(h2.getPosition())) {
                return 0;
            } else {
                return -1;
            }
        }
    }

    /**
     * 格式化权限按钮位置说明
     * 1侧边栏权限 2头部权限 3静默加载
     * */
    private String formatterPosition(int pos){
        var strPos = "";
        switch (pos){
            case 1:
                strPos = "R: ";
                break;
            case 2:
                strPos = "T: ";
                break;
            case 3:
                strPos = "B: ";
                break;
        }
        return strPos;
    }



}
